Passed
Push — master ( 47d57a...8fd42c )
by Kolja
01:36
created

jgfGraph.js ➔ _getJsonMetadata   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A jgfGraph.js ➔ getNodeById 0 3 1
1
const check = require('check-types');
2
const _ = require('lodash');
3
const { JgfEdge } = require('./jgfEdge');
4
const { Guard } = require('./guard');
5
6
/**
7
 * A single Jgf graph instance, always contained in a parent JgfContainer
8
 */
9
class JgfGraph {
10
11
    /**
12
     * Constructor
13
     * @param {string} type graph classification
14
     * @param {string} label a text display for the graph
15
     * @param {boolean} directed true for a directed graph, false for an undirected graph
16
     * @param {object,null} metadata about the graph
17
     */
18
    constructor(type = '', label = '', directed = true, metadata = null) {
19
        this._nodes = [];
20
        this._edges = [];
21
22
        this.type = type;
23
        this.label = label;
24
        this.directed = directed;
25
        this._metadata = metadata;
26
    }
27
28
    /**
29
     * @param {string} nodeId Node to be found.
30
     * @private
31
     */
32
    _findNodeById(nodeId) {
33
        let foundNode = _.find(this._nodes, (existingNode) => existingNode.id === nodeId);
34
        if (!foundNode) {
35
            throw new Error(`A node does not exist with id = ${nodeId}`);
36
        }
37
38
        return foundNode;
39
    }
40
41
    /**
42
     * @param {JgfNode} node Node to be found.
43
     * @private
44
     */
45
    _nodeExists(node) {
46
        return this._nodeExistsById(node.id);
47
    }
48
49
    /**
50
     * @param {string} nodeId Node to be found.
51
     * @private
52
     */
53
    _nodeExistsById(nodeId) {
54
        let foundNode = _.find(this._nodes, (existingNode) => existingNode.id === nodeId);
55
56
        return Boolean(foundNode);
57
    }
58
59
    /**
60
     * Set the graph meta data
61
     */
62
    set metadata(value) {
63
        Guard.assertValidMetadataOrNull(value);
64
        this._metadata = value;
65
    }
66
67
    /**
68
     * Returns the graph meta data
69
     */
70
    get metadata() {
71
        return this._metadata;
72
    }
73
74
    /**
75
     * Returns all nodes
76
     */
77
    get nodes() {
78
        return this._nodes;
79
    }
80
81
    /**
82
     * Returns all edges
83
     */
84
    get edges() {
85
        return this._edges;
86
    }
87
88
    /**
89
     * Adds a new node
90
     * @param {JgfNode} node Node to be added.
91
     */
92
    addNode(node) {
93
        if (this._nodeExists(node)) {
94
            throw new Error(`A node already exists with id = ${node.id}`);
95
        }
96
97
        this._nodes.push(node);
98
    }
99
100
101
    /**
102
     * Adds multiple nodes
103
     * @param {JgfNode[]} nodes A collection of Jgf node objects.
104
     */
105
    addNodes(nodes) {
106
        for (let node of nodes) {
107
            this.addNode(node);
108
        }
109
    }
110
111
    /**
112
     * Removes an existing graph node
113
     * @param {JgfNode} node Node to be removed.
114
     */
115
    removeNode(node) {
116
        if (!this._nodeExists(node)) {
117
            throw new Error(`A node does not exist with id = ${node.id}`);
118
        }
119
120
        _.remove(this._nodes, (existingNode) => existingNode.id === node.id);
121
    }
122
123
    /**
124
     * Get a node by a node id.
125
     * @param {string} nodeId Unique node id
126
     */
127
    getNodeById(nodeId) {
128
        return this._findNodeById(nodeId);
129
    }
130
131
    /**
132
     * Adds an edge between a source node and a target node.
133
     * @param {JgfEdge} edge Source node id
134
     */
135
    addEdge(edge) {
136
        this._guardAgainstNonExistentNodes(edge.source, edge.target);
137
        this._edges.push(edge);
138
    }
139
140
    _guardAgainstNonExistentNodes(source, target) {
141
        if (!this._nodeExistsById(source)) {
142
            throw new Error(`addEdge failed: source node isn't found in nodes. source = ${source}`);
143
        }
144
145
        if (!this._nodeExistsById(target)) {
146
            throw new Error(`addEdge failed: target node isn't found in nodes. target = ${target}`);
147
        }
148
    }
149
150
    /**
151
     * Adds multiple edges
152
     * @param {JgfEdge[]} edges A collection of Jgf edge objects.
153
     */
154
    addEdges(edges) {
155
        for (let edge of edges) {
156
            this.addEdge(edge);
157
        }
158
    }
159
160
    /**
161
     * Removes existing graph edge.
162
     * @param {JgfEdge} edge Edge to be removed.
163
     */
164
    removeEdge(edge) {
165
        _.remove(this._edges, (existingEdge) => existingEdge.isEqualTo(edge, true));
166
    }
167
168
    /**
169
     * Get edges between source node and target node, with an optional edge relation.
170
     * @param {string} source Source node ID.
171
     * @param {string} target Target node ID.
172
     * @param {string,null} relation
173
     */
174
    getEdgesByNodes(source, target, relation = null) {
175
        this._guardAgainstNonExistentNodes(source, target);
176
177
        let edge = new JgfEdge(source, target, relation);
178
179
        return _.filter(this._edges, (existingEdge) => existingEdge.isEqualTo(edge, check.assigned(relation)));
180
    }
181
182
    get graphDimensions() {
183
        return {
184
            nodes: this._nodes.length,
185
            edges: this._edges.length,
186
        };
187
    }
188
}
189
190
module.exports = {
191
    JgfGraph,
192
};